package com.lagou.config;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 采用图的方式保存依赖关系,有向无环图
 *
 * TODO 同一个接口的多个实现,注入到容器时.会出现通过接口查询bean的时候只能查询出来一个. 后期可以加入bean的排序
 * @author: wudong
 * @create: 2021-05-27 17:42
 **/
public class SimpleAliasRegistry implements AliasRegistry {
    Map<String,String> aliasMap = new HashMap<>();

    public static void main(String[] args) {
        SimpleAliasRegistry simpleAliasRegistry = new SimpleAliasRegistry();
        simpleAliasRegistry.registerAlias("1","2");
        simpleAliasRegistry.registerAlias("2","3");
        List<String> reuslt = new ArrayList<>();
        simpleAliasRegistry.registerAlias("4","3");
        System.out.println(simpleAliasRegistry.hasAlias("1","3"));
    }

    @Override
    public void registerAlias(String name, String alias) {
        if(name == null || name.isEmpty()){
            throw new IllegalStateException("name 不能为空");
        }
        if(alias == null || alias.isEmpty()){
            throw new IllegalStateException("name 不能为空");
        }
        if (hasAlias(alias, name)) {
            throw new IllegalStateException("不能注册别名 '" + alias +
                    " 到 " + name + "': 出现循环 ");
        }
        aliasMap.put(alias,name);
    }

    @Override
    public void removeAlias(String alias) {
        this.aliasMap.remove(alias);
    }

    @Override
    public boolean isAlias(String name) {
        return this.aliasMap.containsKey(name);
    }

    @Override
    public String getRealName(String alias) {
        String relname = this.aliasMap.get(alias);
        if(this.aliasMap.containsKey(relname)){
            return getRealName(relname);
        }
        return relname;
    }

    @Override
    public List<String> getAliases(String name) {
        List<String> result = new ArrayList<>();
        retrieveAliases(name, result);
        return result;
    }

    @Override
    public boolean hasAlias(String name, String alias) {
        for (Map.Entry<String, String> entry : this.aliasMap.entrySet()) {
            String registeredName = entry.getValue();
            if (registeredName.equals(name)) {
                String registeredAlias = entry.getKey();
                if (registeredAlias.equals(alias) || hasAlias(registeredAlias, alias)) {
                    return true;
                }
            }
        }
        return false;
    }

    private void retrieveAliases(String name, List<String> result) {
        this.aliasMap.forEach((alias, registeredName) -> {
            if (registeredName.equals(name)) {
                result.add(alias);
                retrieveAliases(alias, result);
            }
        });
    }


}
